package com.my.client;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.my.api.MyRpcRequest;
import com.my.api.MyRpcResponse;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyRpcInvocationHandler implements InvocationHandler {
    // 要代理的类
    private Class<?> clz;
    // 要调用的远端服务地址
    private String remoteUrl;

    public MyRpcInvocationHandler(Class<?> clz, String remoteUrl) {
        this.clz = clz;
        this.remoteUrl = remoteUrl;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 封装参数
        MyRpcRequest rpcRequest = new MyRpcRequest();
        rpcRequest.setMethod(method.getName());
        rpcRequest.setServiceClass(this.clz.getName()); // 全限定名称
        rpcRequest.setParams(args);
        MyRpcResponse response = post(rpcRequest, this.remoteUrl);
        // json中在服务提供者端写入了@type信息，会自动解析对应类型的对象，但需要在这里添加白名单，否则抛出异常autoType is not support xxx
        // https://blog.csdn.net/cdyjy_litao/article/details/72458538
        ParserConfig.getGlobalInstance().addAccept("com.my");
        Object result = JSON.parse(response.getResult().toString());
        return result;
    }
    public static final MediaType JSONTYPE = MediaType.get("application/json; charset=utf-8");

    private static MyRpcResponse post(MyRpcRequest req, String url) throws IOException {
        // 序列化方式：使用基于json文本的序列化
        String reqJson = JSON.toJSONString(req);
        System.out.println("req json: "+reqJson);

        // 1.可以复用client
        // 2.尝试使用httpclient或者netty client
        OkHttpClient client = new OkHttpClient();
        final Request request = new Request.Builder()
                .url(url)
                .post(RequestBody.create(JSONTYPE, reqJson))
                .build();
        String respJson = client.newCall(request).execute().body().string();
        System.out.println("resp json: "+respJson);
        return JSON.parseObject(respJson, MyRpcResponse.class);
    }

}
